; Published under the MIT License

; Copyright(c) 2010 Ajtaji and Zenner

; Permission is hereby granted, free of charge, To any person obtaining a copy
; of this software And associated documentation files(the "Software"), To deal
; in the Software without restriction, including without limitation the rights
; To use, copy, modify, merge, publish, distribute, sublicense, And/Or sell
; copies of the Software, And To permit persons To whom the Software is
; furnished To do so, subject To the following conditions :

; The above copyright notice And this permission notice shall be included in
; all copies Or substantial portions of the Software.

; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS Or
; IMPLIED, INCLUDING BUT Not LIMITED To THE WARRANTIES OF MERCHANTABILITY,
; FITNESS For A PARTICULAR PURPOSE And NONINFRINGEMENT.IN NO EVENT SHALL THE
; AUTHORS Or COPYRIGHT HOLDERS BE LIABLE For ANY CLAIM, DAMAGES Or OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT Or OTHERWISE, ARISING FROM,
; OUT OF Or IN CONNECTION With THE SOFTWARE Or THE USE Or OTHER DEALINGS IN
; THE SOFTWARE.






;CompilerIf #Directory
  XIncludeFile "..\openglengine\OpenGLBackbone2.pb"
; CompilerElse
;   XIncludeFile "OpenGLBackbone2.pb"
; CompilerEndIf


Procedure GLFlipBuffers(dummy)
  glFlush()
  SwapBuffers_(hDC);
  ;Debug hdc
EndProcedure
Procedure GLClearScreen(Value=#Null)
  glClear(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT) ;Clear The Screen And The Depth Buffer
  
  EndProcedure
 
;- TODO: most of this is still hard-coded
Procedure GLDrawWindow(WindowX.l, WindowY.l, WindowWidth.l, WindowHeight.l)
  ;   BorderWidth = 4
  ;   WorkAreaX = WindowX + BorderWidth
  ;   WorkAreaY = WindowY + BorderWidth
  ;   WorkWidth = WindowWidth - BorderWidth
  ;   WorkHeight = WindowHeight - BorderWidth
  ;
  ;   ClearScreen(RGB(255, 255, 255))
  ;
  ;   DisplaySprite(5, WindowX, WindowY)                                              ;Drawing Top Left Corner
  ;
  ;   For x = 0 To WindowWidth - BorderWidth * 2                                      ;Drawing Top Border
  ;     DisplaySprite(1, BorderWidth + WindowX + X, WindowY)
  ;   Next x
  ;
  ;   DisplaySprite(6, WindowX + WindowWidth, WindowY)                                ;Drawing Top Right Corner
  ;
  ;   For x = 0 To WindowWidth - BorderWidth * 2                                      ;Drawing Bottom Border
  ;     DisplaySprite(2, BorderWidth + WindowX + x, WindowY + WindowHeight)
  ;   Next x
  ;
  ;   DisplaySprite(7, WindowX, WindowY + WindowHeight)                               ;Drawing Bottom Left Corner
  ;
  ;   For x = 0 To WindowHeight - BorderWidth * 2                                     ;Drawing Left Border
  ;     DisplaySprite(3, WindowX, BorderWidth + WindowY + x)
  ;   Next x
  ;
  ;   DisplaySprite(8, WindowX + WindowWidth, WindowY + WindowHeight)                 ;Drawing Bottom Right Corner
  ;
  ;   For x = 0 To WindowHeight - BorderWidth * 2                                     ;Drawing Right Border
  ;     DisplaySprite(4, WindowX + WindowWidth, BorderWidth + WindowY + x)
  ;   Next x
  ;
  ;   ProcedureReturn GrabSprite(100, WindowX, WindowY, WindowWidth + 4, WindowHeight + 4, 0)
  ;
EndProcedure

Procedure GLDeleteSprite ( number.l )
  
  ; If spritecontainer.spriteinfo(number)\imagenumber<>0 And numberofsprites>-1
  ; Protected a,b
  
  ; For a=1 To numberofsprites
  ; If spriteindex ( a )=number
  ;   For b=a To numberofsprites
  ;   spriteindex(a)=spriteindex(a+1)
  ;   Next b
  ;   numberofsprites-1
  spritecontainer.spriteinfo(number)\imagenumber=0
  spritecontainer.spriteinfo(number)\alpha=0
  spritecontainer.spriteinfo(number)\usingAlpha=0
  spritecontainer.spriteinfo(number)\transparentcolor=0
  spritecontainer.spriteinfo(number)\IsBeingDisplayed=0
  SpriteContainer.Spriteinfo(number)\OffSetY=0
  SpriteContainer.Spriteinfo(number)\OffSetX=0
  ;
  ;
  ;   ProcedureReturn
  ; EndIf
  ; Next a
  ; EndIf
  
EndProcedure

Procedure GLDisplaySprites(number.l)
  
  If spritecontainer.spriteinfo(number)\imageNumber=0
    ProcedureReturn
  EndIf
  If spritecontainer.spriteinfo(number)\Usingalpha<>0
    ;DisplayTransparentSprite(SpriteContainer.Spriteinfo(number)\imagenumber,SpriteContainer.Spriteinfo(number)\x+SpriteContainer.Spriteinfo(number)\OffSetX,SpriteContainer.Spriteinfo(number)\y+SpriteContainer.Spriteinfo(number)\OffSetY,SpriteContainer.Spriteinfo(number)\alpha)
  Else
    GldrawSprite(SpriteContainer.Spriteinfo(number)\imagenumber,SpriteContainer.Spriteinfo(number)\x+SpriteContainer.Spriteinfo(number)\OffSetX,SpriteContainer.Spriteinfo(number)\y+SpriteContainer.Spriteinfo(number)\OffSetY)
    ;DisplayTransparentSprite(SpriteContainer.Spriteinfo(number)\imagenumber,SpriteContainer.Spriteinfo(number)\x+SpriteContainer.Spriteinfo(number)\OffSetX,SpriteContainer.Spriteinfo(number)\y+SpriteContainer.Spriteinfo(number)\OffSetY)
  EndIf
  ; If spritecontainer.spriteinfo(SpriteIndex(number))\IsBeingDisplayed <> 1  ;- tim edit
  ;   If spritecontainer.spriteinfo(SpriteIndex(number))\imageNumber=0
  ;     ProcedureReturn
  ;   EndIf
  ;     If spritecontainer.spriteinfo(SpriteIndex(number))\Usingalpha<>0
  ;       DisplayTranslucentSprite(SpriteContainer.Spriteinfo(SpriteIndex(number))\imagenumber,SpriteContainer.Spriteinfo(number)\x,SpriteContainer.Spriteinfo(number)\y,SpriteContainer.Spriteinfo(number)\alpha)
  ;     Else
  ;       DisplayTransparentSprite(SpriteContainer.Spriteinfo(SpriteIndex(number))\imagenumber,SpriteContainer.Spriteinfo(number)\x,SpriteContainer.Spriteinfo(number)\y)
  ;     EndIf
  ; EndIf
  
EndProcedure

Procedure glsprite(number.l,posx.l,posy.l,Image.l)
  
  ; If spritecontainer.spriteinfo(number)\imagenumber=0
  ;   NumberOfSprites+1
  ;   SpriteIndex(numberofsprites)=number
  ;
  ; EndIf
  SpriteContainer.Spriteinfo(number)\x=posx
  SpriteContainer.Spriteinfo(number)\y=posy
  SpriteContainer.Spriteinfo(number)\ImageNumber=Image
  
EndProcedure

Procedure GLpastesprite(number, posx, posy)
  
  SpriteContainer.Spriteinfo(number)\x = posx
  SpriteContainer.Spriteinfo(number)\y = posy
  
EndProcedure

Procedure GLSetSpriteAlpha(number.l, alpha)
  
  SpriteContainer.Spriteinfo(number)\UsingAlpha = 1
  SpriteContainer.Spriteinfo(number)\alpha = alpha
  
EndProcedure

Procedure text(posx, posy, string.s, textcolor = -1)
  textcounter + 1
  
  strings.textinfo(textcounter)\posx = posx
  strings.textinfo(textcounter)\posy = posy
  strings.textinfo(textcounter)\string = string
  strings(textcounter)\red = fastred(textcolor)
  strings(textcounter)\green = fastgreen(textcolor)
  strings(textcounter)\blue = fastblue(textcolor)
  strings(textcounter)\listbase = fontBase    ;whatever our global font tracking variable is
  
EndProcedure

Procedure BuildFont(fontNum, fontFace$, fontSize = -12) ;Build Our Font Display List
  ;**************************************************************************
  ;This function builds the fonts, in any size shape or matter you need.
  ;Use SelectFont() to set the font you want to draw with
  ;**************************************************************************
  fontBase(fontNum) = glGenLists(96)
  font = CreateFont_(fontSize, 0, 0, 0, #FW_BOLD, 0, 0, 0, #ANSI_CHARSET, #OUT_TT_PRECIS, #CLIP_DEFAULT_PRECIS, #NONANTIALIASED_QUALITY, #FF_DONTCARE | #DEFAULT_PITCH, fontFace$)
  SelectObject_(hDC, font)
  wglUseFontBitmaps_(hDC, 32, 96, fontBase(fontNum))  
  
  ProcedureReturn fontNum
EndProcedure

Procedure SelectFont(fontNum)
  ;**********************************************************
  ;This function sets the global fontBase variable 
  ;that will be picked up by the raster commands to draw in
  ;the font that you specify.
  ;Note: "fontbase" is our global to the current fontbase(list)
  ;**********************************************************
  fontbase = fontBase(fontNum)
EndProcedure

Procedure KillFont(fontNum) ;Delete The Font List
  
  glDeleteLists_(fontBase(fontNum),256) ;Delete All 96 Characters
  
EndProcedure

Procedure glWIndowPos4MESAemulate(x.f, y.f, z.f, w.f)
  ;// Push current matrix mode and viewport attributes 
  glPushAttrib_(#GL_TRANSFORM_BIT | #GL_VIEWPORT_BIT)
  
    ;// Setup projection parameters 
    glMatrixMode(#GL_PROJECTION)
    glPushMatrix()
      glLoadIdentity()
      glMatrixMode(#GL_MODELVIEW)
      glPushMatrix()
        glLoadIdentity()
        glDepthRange(z,z)
        glViewPort(x - 1, y - 1, 2, 2)
        ;// Set the raster (window) position
        fx.f = x - Int(x)
        fy.f = y - Int(y)
        glRasterPos4f(fx, fy, 0.0, w)
      ;// Restore matrices, viewport and matrix mode
      glPopMatrix()
    glMatrixMode(#GL_PROJECTION)
    glPopMatrix()
    
  glPopAttrib()
  
    
EndProcedure

Procedure glWindowPos2MESAemulate(x.f, y.f)
  glWindowPos4MESAemulate(x, y, 0, 1)
EndProcedure

Procedure glPrint(x.f, y.f, string.s, listbase) ;Where The Printing Happens
  
  glLoadIdentity()
  
  Protected i
  
  ;// handles new line characters
  string = string + "\n"
  cnt = CountString(string, "\n")
  spacer = 0
  
  For i = 1 To cnt
    ;// Position the text on the screen
    glRasterPos2f(x, y + spacer)
    
    ;// An example to translate to screen coordinates -- works good but is opengl coordinates 0,0 bot left
    ;glWindowPos2MESAemulate(x, y)
    
    line.s = ReplaceString(string, "\n", Chr(10))
    line = StringField(line, i, Chr(10))
    
    ;    glPushAttrib(#GL_LIST_BIT);moved to glsync, use text to print with
    glListBase(listbase-32) ;Choose The Font Set (0 or 1)
    glCallLists(Len(line), #GL_UNSIGNED_BYTE, line) ;Write The Text To The Screen
    ;    glPopAttrib()  Moved to glsync, use text to print with
    
    spacer + 15
  Next
  
EndProcedure

Procedure GLsync()
  ;Sleep_(10)
  Protected a, b, c, d, counter
  ;StartSpecialFX()
  ;********************************************************************
  ;BackDropColor in this call is a dummy, it is set in GLColorBackdrop
  ;GLClearScreen(backdropcolor)
  ;********************************************************************
  ;   CompilerIf #Directory
  ;     For a = 1 To 1000
  ;     CompilerElse
  
  For a = 1 To 60000
    ;      CompilerEndIf
    If SpriteContainer(a)\ImageNumber=0   
      Continue      ;optimization! skip to next this sprite has prob been deleted.
    EndIf
    
    If SpriteContainer(a)\color = 0
      SpriteContainer(a)\color=rgb32(255,255,255,255)
    EndIf
    glColor4ub(FastRed(SpriteContainer(a)\color), FastGreen(SpriteContainer(a)\color), FastBlue(SpriteContainer(a)\color),255)
    GLdisplaysprites(a)
  Next a
  
  
  ;*********************************************************************
  ;Handles Rastering Text/Fonts
  ;*********************************************************************
  If textcounter>0                ;if there is text to output
    glPushAttrib(#GL_LIST_BIT)    ;push!
    
    gldisable(#GL_TEXTURE_2D)     ;disable 2d texture because of blending issues on nvidia hardware
    
    For a = 1 To textcounter      ;global array strings() holds all our text to output
      ;use color from text() function
      glColor4ub(strings(a)\red, strings(a)\green, strings(a)\blue, 255)
      
      ;this is where the text is actually drawn to screen
      glPrint(strings(a)\posx, strings(a)\posy, strings(a)\string, strings(a)\listbase)
    Next a
    
    glPopAttrib()                 ;pop back our attributes
    
    textcounter = 0               ;reset text counter
    
    glEnable(#GL_TEXTURE_2D)      ;renable 2d textures
  EndIf
  
  glflush()                       ;not sure this is needed YES, it always needed! must cleanup operations before Flipbuffer
  ;end Rastering Text/Fonts
  ;********************************************************************
  
  
  If fullscreen=1
    GLFlipBuffers(1)
  Else
    GLFlipBuffers(0)
  EndIf
  


EndProcedure


Procedure GLHideSprite(number.l)
  spritecontainer.spriteinfo(number)\IsBeingDisplayed = 1
EndProcedure

Procedure GLShowSprite(number.l)
  spritecontainer.spriteinfo(number)\IsBeingDisplayed = 0
EndProcedure

Procedure GLCloneSprite(CloneFromSprite.l, CloneToSprite.l); , Mode.l
  ;CopySprite(SpriteContainer.spriteinfo(CloneFromSprite)\ImageNumber, SpriteContainer.spriteinfo(CloneToSprite)\ImageNumber, Mode)
  ;SpriteContainer.Spriteinfo(number)\x=posx
  ;SpriteContainer.Spriteinfo(number)\y=posy
  SpriteContainer(CloneToSprite.l)\imagenumber = SpriteContainer(ClonefromSprite)\imagenumber
  SpriteContainer(CloneToSprite.l)\imagelist = SpriteContainer(ClonefromSprite)\imagelist
EndProcedure

Procedure GLSpriteOffsetX(number, Offset)
  SpriteContainer.Spriteinfo(number)\OffSetX = OffSet
EndProcedure

Procedure GLSpriteOffsetY(number, OffSet)
  SpriteContainer.Spriteinfo(number)\OffSetY = Offset
EndProcedure

Procedure GLColorBackdrop(color.l)
  glClearColor(Red(color)/256, Green(color)/256, Blue(color)/256, 1) : ;` Clear The Background Color To Black
  BackDropColor = color
EndProcedure
Procedure SetSpriteColorBlend(Sprite, color);set color to blend into Original sprite colors
  SpriteContainer(Sprite)\color = color
  
EndProcedure

; IDE Options = PureBasic 4.51 (Windows - x86)
; CursorPosition = 264
; Folding = ----
; EnableThread
; Warnings = Display